{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "3xW4O0zuKfWD"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "from openai import OpenAI, pydantic_function_tool\n",
        "import rich\n",
        "import requests\n",
        "import json\n",
        "from pydantic import BaseModel, Field\n",
        "from google.colab import userdata"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "api_key = userdata.get('OPENAI_API_KEY')\n",
        "MODEL = \"gpt-4o-mini\"\n",
        "\n",
        "openai = OpenAI(api_key=api_key)"
      ],
      "metadata": {
        "id": "vUydnLeLKs03"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "**Calling the same function multiple times when response from Chat API and Responses API requires to call function multiple times**"
      ],
      "metadata": {
        "id": "blCx6gu1Vl46"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "The Pydantic-generated function structure is acceptable in OpenAI's Chat API, but the Responses API requires a slightly different structure."
      ],
      "metadata": {
        "id": "nznKPApuXC9z"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "class GetWeather(BaseModel):\n",
        "    latitude: float = Field(..., description=\"Latitude of the location\")\n",
        "    longitude: float = Field(..., description=\"Longitude of the location\")\n",
        "\n",
        "def get_weather(latitude, longitude):\n",
        "    response = requests.get(f\"https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&current=temperature_2m,wind_speed_10m&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m\")\n",
        "    data = response.json()\n",
        "    print(f\"get_weather function called to get weather for latitude = {latitude}, longitude = {longitude}\")\n",
        "    print(f\"And result is  = {data['current']['temperature_2m']}\")\n",
        "    return data['current']['temperature_2m']\n",
        "\n",
        "# Notice the function property in the output, which is not acceptable in Responses API\n",
        "rich.print(pydantic_function_tool(GetWeather))"
      ],
      "metadata": {
        "id": "qvJhp-k5XEmW",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 289
        },
        "outputId": "c03ca065-a192-4d1a-ed15-8cd83ff856e8"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m{\u001b[0m\n",
              "    \u001b[32m'type'\u001b[0m: \u001b[32m'function'\u001b[0m,\n",
              "    \u001b[32m'function'\u001b[0m: \u001b[1m{\u001b[0m\n",
              "        \u001b[32m'name'\u001b[0m: \u001b[32m'GetWeather'\u001b[0m,\n",
              "        \u001b[32m'strict'\u001b[0m: \u001b[3;92mTrue\u001b[0m,\n",
              "        \u001b[32m'parameters'\u001b[0m: \u001b[1m{\u001b[0m\n",
              "            \u001b[32m'properties'\u001b[0m: \u001b[1m{\u001b[0m\n",
              "                \u001b[32m'latitude'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'description'\u001b[0m: \u001b[32m'Latitude of the location'\u001b[0m, \u001b[32m'title'\u001b[0m: \u001b[32m'Latitude'\u001b[0m, \u001b[32m'type'\u001b[0m: \u001b[32m'number'\u001b[0m\u001b[1m}\u001b[0m,\n",
              "                \u001b[32m'longitude'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'description'\u001b[0m: \u001b[32m'Longitude of the location'\u001b[0m, \u001b[32m'title'\u001b[0m: \u001b[32m'Longitude'\u001b[0m, \u001b[32m'type'\u001b[0m: \u001b[32m'number'\u001b[0m\u001b[1m}\u001b[0m\n",
              "            \u001b[1m}\u001b[0m,\n",
              "            \u001b[32m'required'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'latitude'\u001b[0m, \u001b[32m'longitude'\u001b[0m\u001b[1m]\u001b[0m,\n",
              "            \u001b[32m'title'\u001b[0m: \u001b[32m'GetWeather'\u001b[0m,\n",
              "            \u001b[32m'type'\u001b[0m: \u001b[32m'object'\u001b[0m,\n",
              "            \u001b[32m'additionalProperties'\u001b[0m: \u001b[3;91mFalse\u001b[0m\n",
              "        \u001b[1m}\u001b[0m\n",
              "    \u001b[1m}\u001b[0m\n",
              "\u001b[1m}\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">{</span>\n",
              "    <span style=\"color: #008000; text-decoration-color: #008000\">'type'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'function'</span>,\n",
              "    <span style=\"color: #008000; text-decoration-color: #008000\">'function'</span>: <span style=\"font-weight: bold\">{</span>\n",
              "        <span style=\"color: #008000; text-decoration-color: #008000\">'name'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'GetWeather'</span>,\n",
              "        <span style=\"color: #008000; text-decoration-color: #008000\">'strict'</span>: <span style=\"color: #00ff00; text-decoration-color: #00ff00; font-style: italic\">True</span>,\n",
              "        <span style=\"color: #008000; text-decoration-color: #008000\">'parameters'</span>: <span style=\"font-weight: bold\">{</span>\n",
              "            <span style=\"color: #008000; text-decoration-color: #008000\">'properties'</span>: <span style=\"font-weight: bold\">{</span>\n",
              "                <span style=\"color: #008000; text-decoration-color: #008000\">'latitude'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'description'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'Latitude of the location'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'title'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'Latitude'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'type'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'number'</span><span style=\"font-weight: bold\">}</span>,\n",
              "                <span style=\"color: #008000; text-decoration-color: #008000\">'longitude'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'description'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'Longitude of the location'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'title'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'Longitude'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'type'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'number'</span><span style=\"font-weight: bold\">}</span>\n",
              "            <span style=\"font-weight: bold\">}</span>,\n",
              "            <span style=\"color: #008000; text-decoration-color: #008000\">'required'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'latitude'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'longitude'</span><span style=\"font-weight: bold\">]</span>,\n",
              "            <span style=\"color: #008000; text-decoration-color: #008000\">'title'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'GetWeather'</span>,\n",
              "            <span style=\"color: #008000; text-decoration-color: #008000\">'type'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'object'</span>,\n",
              "            <span style=\"color: #008000; text-decoration-color: #008000\">'additionalProperties'</span>: <span style=\"color: #ff0000; text-decoration-color: #ff0000; font-style: italic\">False</span>\n",
              "        <span style=\"font-weight: bold\">}</span>\n",
              "    <span style=\"font-weight: bold\">}</span>\n",
              "<span style=\"font-weight: bold\">}</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# Chat Completion API\n",
        "\n",
        "https://platform.openai.com/docs/guides/function-calling?api-mode=chat"
      ],
      "metadata": {
        "id": "5wlqKfVBKyjD"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "First Step where model will responed with tool call request"
      ],
      "metadata": {
        "id": "EgXT84U9Tfqr"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "messages=[\n",
        "    {\"role\": \"developer\", \"content\": \"You are a helpful assistant and provide update on weather in a city. Response should be courteous and professional.\"},\n",
        "    # {\"role\": \"user\", \"content\": \"What's the weather like in Karachi and Lahore?\"}\n",
        "    # {\"role\": \"user\", \"content\": \"NYC\"}\n",
        "    {\"role\": \"user\", \"content\": \"Berlin and Paris\"} # This time we are sending multiple cities\n",
        "]\n",
        "tools = [pydantic_function_tool(GetWeather)]\n",
        "response = openai.chat.completions.create(\n",
        "    model=MODEL,\n",
        "    messages=messages,\n",
        "    tools = tools\n",
        ")\n",
        "\n",
        "rich.print(response.choices[0])\n",
        "print(\"Finish Reason = \", response.choices[0].finish_reason)\n",
        "# Chat API returns tool_calls for all expected tools in single response\n",
        "rich.print(response.choices[0].message.tool_calls)\n",
        "print(\"Number of tool calls: \",len(response.choices[0].message.tool_calls))"
      ],
      "metadata": {
        "id": "dBrUkMCUKz0s",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 644
        },
        "outputId": "f157e53a-752d-4cf1-9de5-0d73ed3374d6"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1;35mChoice\u001b[0m\u001b[1m(\u001b[0m\n",
              "    \u001b[33mfinish_reason\u001b[0m=\u001b[32m'tool_calls'\u001b[0m,\n",
              "    \u001b[33mindex\u001b[0m=\u001b[1;36m0\u001b[0m,\n",
              "    \u001b[33mlogprobs\u001b[0m=\u001b[3;35mNone\u001b[0m,\n",
              "    \u001b[33mmessage\u001b[0m=\u001b[1;35mChatCompletionMessage\u001b[0m\u001b[1m(\u001b[0m\n",
              "        \u001b[33mcontent\u001b[0m=\u001b[3;35mNone\u001b[0m,\n",
              "        \u001b[33mrefusal\u001b[0m=\u001b[3;35mNone\u001b[0m,\n",
              "        \u001b[33mrole\u001b[0m=\u001b[32m'assistant'\u001b[0m,\n",
              "        \u001b[33mannotations\u001b[0m=\u001b[1m[\u001b[0m\u001b[1m]\u001b[0m,\n",
              "        \u001b[33maudio\u001b[0m=\u001b[3;35mNone\u001b[0m,\n",
              "        \u001b[33mfunction_call\u001b[0m=\u001b[3;35mNone\u001b[0m,\n",
              "        \u001b[33mtool_calls\u001b[0m=\u001b[1m[\u001b[0m\n",
              "            \u001b[1;35mChatCompletionMessageToolCall\u001b[0m\u001b[1m(\u001b[0m\n",
              "                \u001b[33mid\u001b[0m=\u001b[32m'call_bPBYEADmIi7Q3ETIF5YGQT4g'\u001b[0m,\n",
              "                \u001b[33mfunction\u001b[0m=\u001b[1;35mFunction\u001b[0m\u001b[1m(\u001b[0m\u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"latitude\": 52.52, \"longitude\": 13.405\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m, \u001b[33mname\u001b[0m=\u001b[32m'GetWeather'\u001b[0m\u001b[1m)\u001b[0m,\n",
              "                \u001b[33mtype\u001b[0m=\u001b[32m'function'\u001b[0m\n",
              "            \u001b[1m)\u001b[0m,\n",
              "            \u001b[1;35mChatCompletionMessageToolCall\u001b[0m\u001b[1m(\u001b[0m\n",
              "                \u001b[33mid\u001b[0m=\u001b[32m'call_m7KVrHRU7nGz99mM1Xiv5UFP'\u001b[0m,\n",
              "                \u001b[33mfunction\u001b[0m=\u001b[1;35mFunction\u001b[0m\u001b[1m(\u001b[0m\u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"latitude\": 48.8566, \"longitude\": 2.3522\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m, \u001b[33mname\u001b[0m=\u001b[32m'GetWeather'\u001b[0m\u001b[1m)\u001b[0m,\n",
              "                \u001b[33mtype\u001b[0m=\u001b[32m'function'\u001b[0m\n",
              "            \u001b[1m)\u001b[0m\n",
              "        \u001b[1m]\u001b[0m\n",
              "    \u001b[1m)\u001b[0m\n",
              "\u001b[1m)\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">Choice</span><span style=\"font-weight: bold\">(</span>\n",
              "    <span style=\"color: #808000; text-decoration-color: #808000\">finish_reason</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'tool_calls'</span>,\n",
              "    <span style=\"color: #808000; text-decoration-color: #808000\">index</span>=<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
              "    <span style=\"color: #808000; text-decoration-color: #808000\">logprobs</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
              "    <span style=\"color: #808000; text-decoration-color: #808000\">message</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ChatCompletionMessage</span><span style=\"font-weight: bold\">(</span>\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">content</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">refusal</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">role</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'assistant'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">annotations</span>=<span style=\"font-weight: bold\">[]</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">audio</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">function_call</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">tool_calls</span>=<span style=\"font-weight: bold\">[</span>\n",
              "            <span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ChatCompletionMessageToolCall</span><span style=\"font-weight: bold\">(</span>\n",
              "                <span style=\"color: #808000; text-decoration-color: #808000\">id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'call_bPBYEADmIi7Q3ETIF5YGQT4g'</span>,\n",
              "                <span style=\"color: #808000; text-decoration-color: #808000\">function</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">Function</span><span style=\"font-weight: bold\">(</span><span style=\"color: #808000; text-decoration-color: #808000\">arguments</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'{\"latitude\": 52.52, \"longitude\": 13.405}'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'GetWeather'</span><span style=\"font-weight: bold\">)</span>,\n",
              "                <span style=\"color: #808000; text-decoration-color: #808000\">type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'function'</span>\n",
              "            <span style=\"font-weight: bold\">)</span>,\n",
              "            <span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ChatCompletionMessageToolCall</span><span style=\"font-weight: bold\">(</span>\n",
              "                <span style=\"color: #808000; text-decoration-color: #808000\">id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'call_m7KVrHRU7nGz99mM1Xiv5UFP'</span>,\n",
              "                <span style=\"color: #808000; text-decoration-color: #808000\">function</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">Function</span><span style=\"font-weight: bold\">(</span><span style=\"color: #808000; text-decoration-color: #808000\">arguments</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'{\"latitude\": 48.8566, \"longitude\": 2.3522}'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'GetWeather'</span><span style=\"font-weight: bold\">)</span>,\n",
              "                <span style=\"color: #808000; text-decoration-color: #808000\">type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'function'</span>\n",
              "            <span style=\"font-weight: bold\">)</span>\n",
              "        <span style=\"font-weight: bold\">]</span>\n",
              "    <span style=\"font-weight: bold\">)</span>\n",
              "<span style=\"font-weight: bold\">)</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Finish Reason =  tool_calls\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m[\u001b[0m\n",
              "    \u001b[1;35mChatCompletionMessageToolCall\u001b[0m\u001b[1m(\u001b[0m\n",
              "        \u001b[33mid\u001b[0m=\u001b[32m'call_bPBYEADmIi7Q3ETIF5YGQT4g'\u001b[0m,\n",
              "        \u001b[33mfunction\u001b[0m=\u001b[1;35mFunction\u001b[0m\u001b[1m(\u001b[0m\u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"latitude\": 52.52, \"longitude\": 13.405\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m, \u001b[33mname\u001b[0m=\u001b[32m'GetWeather'\u001b[0m\u001b[1m)\u001b[0m,\n",
              "        \u001b[33mtype\u001b[0m=\u001b[32m'function'\u001b[0m\n",
              "    \u001b[1m)\u001b[0m,\n",
              "    \u001b[1;35mChatCompletionMessageToolCall\u001b[0m\u001b[1m(\u001b[0m\n",
              "        \u001b[33mid\u001b[0m=\u001b[32m'call_m7KVrHRU7nGz99mM1Xiv5UFP'\u001b[0m,\n",
              "        \u001b[33mfunction\u001b[0m=\u001b[1;35mFunction\u001b[0m\u001b[1m(\u001b[0m\u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"latitude\": 48.8566, \"longitude\": 2.3522\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m, \u001b[33mname\u001b[0m=\u001b[32m'GetWeather'\u001b[0m\u001b[1m)\u001b[0m,\n",
              "        \u001b[33mtype\u001b[0m=\u001b[32m'function'\u001b[0m\n",
              "    \u001b[1m)\u001b[0m\n",
              "\u001b[1m]\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">[</span>\n",
              "    <span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ChatCompletionMessageToolCall</span><span style=\"font-weight: bold\">(</span>\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'call_bPBYEADmIi7Q3ETIF5YGQT4g'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">function</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">Function</span><span style=\"font-weight: bold\">(</span><span style=\"color: #808000; text-decoration-color: #808000\">arguments</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'{\"latitude\": 52.52, \"longitude\": 13.405}'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'GetWeather'</span><span style=\"font-weight: bold\">)</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'function'</span>\n",
              "    <span style=\"font-weight: bold\">)</span>,\n",
              "    <span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ChatCompletionMessageToolCall</span><span style=\"font-weight: bold\">(</span>\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'call_m7KVrHRU7nGz99mM1Xiv5UFP'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">function</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">Function</span><span style=\"font-weight: bold\">(</span><span style=\"color: #808000; text-decoration-color: #808000\">arguments</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'{\"latitude\": 48.8566, \"longitude\": 2.3522}'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'GetWeather'</span><span style=\"font-weight: bold\">)</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'function'</span>\n",
              "    <span style=\"font-weight: bold\">)</span>\n",
              "<span style=\"font-weight: bold\">]</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Number of tool calls:  2\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "Second Step where we are calling the `get_weather` function and sending the response back to Chat API.\n",
        "\n",
        "But this time we are running a loop on `tool_call` to call all the functions"
      ],
      "metadata": {
        "id": "xvVxw5mGXWJ6"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Defining a function in which we will loop through the tool_calls,\n",
        "# invoke the corresponding functions, and update the response.\n",
        "# Plus, we will append a new message for each function call to promptMessages.\n",
        "def handle_tool_call(promptMessages, responseMessage):\n",
        "    # Looping on tool_calls\n",
        "    for tool_call in responseMessage.tool_calls:\n",
        "        arguments = json.loads(tool_call.function.arguments)\n",
        "        weather = get_weather(**arguments)\n",
        "        new_message = {\n",
        "            \"role\": \"tool\",\n",
        "            \"content\": str(weather),\n",
        "            \"tool_call_id\": tool_call.id\n",
        "        }\n",
        "        promptMessages.append(new_message)"
      ],
      "metadata": {
        "id": "WItchxDLK2x6"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "if response.choices[0].finish_reason == \"tool_calls\": # Check if finish_reason is tool_calls\n",
        "    # Important: first we will append the previous message (response.choices[0].message) in\n",
        "    # message history and then iterate through tool_calls\n",
        "    messages.append(response.choices[0].message)\n",
        "    handle_tool_call(messages, response.choices[0].message)\n",
        "    response2 = openai.chat.completions.create(model=MODEL, messages=messages, tools=tools)\n",
        "    print(\"Model Response2 = \",response2.choices[0].message.content)\n",
        "    print(\"Finish Reason = \",response2.choices[0].finish_reason)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "TFXLJ2KIbtqa",
        "outputId": "b2e928ec-ba73-469f-ef06-befc1b6d0c7f"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "get_weather function called to get weather for latitude = 52.52, longitude = 13.405\n",
            "And result is  = 7.8\n",
            "get_weather function called to get weather for latitude = 48.8566, longitude = 2.3522\n",
            "And result is  = 13.5\n",
            "Model Response2 =  The current weather updates are as follows:\n",
            "\n",
            "- **Berlin:** The temperature is approximately 7.8°C.\n",
            "- **Paris:** The temperature is around 13.5°C.\n",
            "\n",
            "If you need any further information, feel free to ask!\n",
            "Finish Reason =  stop\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# Responses API\n",
        "\n",
        "https://platform.openai.com/docs/guides/function-calling?api-mode=responses"
      ],
      "metadata": {
        "id": "tCzSosP5K-JR"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "rich.print(pydantic_function_tool(GetWeather))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 289
        },
        "id": "tCSmj7fRaItb",
        "outputId": "1b30cf84-9e50-4156-8e04-477de8c30ee7"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m{\u001b[0m\n",
              "    \u001b[32m'type'\u001b[0m: \u001b[32m'function'\u001b[0m,\n",
              "    \u001b[32m'function'\u001b[0m: \u001b[1m{\u001b[0m\n",
              "        \u001b[32m'name'\u001b[0m: \u001b[32m'GetWeather'\u001b[0m,\n",
              "        \u001b[32m'strict'\u001b[0m: \u001b[3;92mTrue\u001b[0m,\n",
              "        \u001b[32m'parameters'\u001b[0m: \u001b[1m{\u001b[0m\n",
              "            \u001b[32m'properties'\u001b[0m: \u001b[1m{\u001b[0m\n",
              "                \u001b[32m'latitude'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'description'\u001b[0m: \u001b[32m'Latitude of the location'\u001b[0m, \u001b[32m'title'\u001b[0m: \u001b[32m'Latitude'\u001b[0m, \u001b[32m'type'\u001b[0m: \u001b[32m'number'\u001b[0m\u001b[1m}\u001b[0m,\n",
              "                \u001b[32m'longitude'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'description'\u001b[0m: \u001b[32m'Longitude of the location'\u001b[0m, \u001b[32m'title'\u001b[0m: \u001b[32m'Longitude'\u001b[0m, \u001b[32m'type'\u001b[0m: \u001b[32m'number'\u001b[0m\u001b[1m}\u001b[0m\n",
              "            \u001b[1m}\u001b[0m,\n",
              "            \u001b[32m'required'\u001b[0m: \u001b[1m[\u001b[0m\u001b[32m'latitude'\u001b[0m, \u001b[32m'longitude'\u001b[0m\u001b[1m]\u001b[0m,\n",
              "            \u001b[32m'title'\u001b[0m: \u001b[32m'GetWeather'\u001b[0m,\n",
              "            \u001b[32m'type'\u001b[0m: \u001b[32m'object'\u001b[0m,\n",
              "            \u001b[32m'additionalProperties'\u001b[0m: \u001b[3;91mFalse\u001b[0m\n",
              "        \u001b[1m}\u001b[0m\n",
              "    \u001b[1m}\u001b[0m\n",
              "\u001b[1m}\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">{</span>\n",
              "    <span style=\"color: #008000; text-decoration-color: #008000\">'type'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'function'</span>,\n",
              "    <span style=\"color: #008000; text-decoration-color: #008000\">'function'</span>: <span style=\"font-weight: bold\">{</span>\n",
              "        <span style=\"color: #008000; text-decoration-color: #008000\">'name'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'GetWeather'</span>,\n",
              "        <span style=\"color: #008000; text-decoration-color: #008000\">'strict'</span>: <span style=\"color: #00ff00; text-decoration-color: #00ff00; font-style: italic\">True</span>,\n",
              "        <span style=\"color: #008000; text-decoration-color: #008000\">'parameters'</span>: <span style=\"font-weight: bold\">{</span>\n",
              "            <span style=\"color: #008000; text-decoration-color: #008000\">'properties'</span>: <span style=\"font-weight: bold\">{</span>\n",
              "                <span style=\"color: #008000; text-decoration-color: #008000\">'latitude'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'description'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'Latitude of the location'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'title'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'Latitude'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'type'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'number'</span><span style=\"font-weight: bold\">}</span>,\n",
              "                <span style=\"color: #008000; text-decoration-color: #008000\">'longitude'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'description'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'Longitude of the location'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'title'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'Longitude'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'type'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'number'</span><span style=\"font-weight: bold\">}</span>\n",
              "            <span style=\"font-weight: bold\">}</span>,\n",
              "            <span style=\"color: #008000; text-decoration-color: #008000\">'required'</span>: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'latitude'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'longitude'</span><span style=\"font-weight: bold\">]</span>,\n",
              "            <span style=\"color: #008000; text-decoration-color: #008000\">'title'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'GetWeather'</span>,\n",
              "            <span style=\"color: #008000; text-decoration-color: #008000\">'type'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'object'</span>,\n",
              "            <span style=\"color: #008000; text-decoration-color: #008000\">'additionalProperties'</span>: <span style=\"color: #ff0000; text-decoration-color: #ff0000; font-style: italic\">False</span>\n",
              "        <span style=\"font-weight: bold\">}</span>\n",
              "    <span style=\"font-weight: bold\">}</span>\n",
              "<span style=\"font-weight: bold\">}</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "To use pydantic-generated function, we need to use `openai.responses.parse()` function call\n",
        "\n",
        "https://github.com/openai/openai-python/blob/main/examples/responses/structured_outputs_tools.py"
      ],
      "metadata": {
        "id": "X__yLWt7aIOU"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "Sometimes Responses API is not sending weather function call for all cities in one go.\n",
        "It is totally depends on model how it will organized the call of function, all in one go or one by one"
      ],
      "metadata": {
        "id": "p87WEKKmcB9L"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "messages=[\n",
        "    {\"role\": \"developer\", \"content\": \"You are a helpful assistant and provide update on weather in a city. Response should be courteous and professional.\"},\n",
        "    # {\"role\": \"user\", \"content\": \"What's the weather like in Karachi and Lahore?\"}\n",
        "    {\"role\": \"user\", \"content\": \"Berlin and Paris\"}\n",
        "]\n",
        "# messages=[\n",
        "#     {\"role\": \"developer\", \"content\": \"You are a helpful assistant and provide update on weather in all the cities as asked by user. Response should be courteous and professional.\"},\n",
        "#     {\"role\": \"user\", \"content\": \"What's the weather in following cities Karachi and Lahore?\"}\n",
        "# ]\n",
        "tools = [pydantic_function_tool(GetWeather)]\n",
        "\n",
        "# Sometimes Responses API is not sending weather function call for all cities in one go.\n",
        "# It is totally depends on model how it will organized the call of function, all in one go or one by one\n",
        "response = openai.responses.parse(\n",
        "    model=MODEL,\n",
        "    input=messages,\n",
        "    tools = tools\n",
        ")\n",
        "\n",
        "print(\"Status = \",response.status) # Status will not indicate the tool call\n",
        "print(response.output_text) # Empty\n",
        "rich.print(response.output)\n",
        "# In this case Responses API calling tools one by one. We need to send the response for the first\n",
        "# tool call to the API, after which the Responses API will send the next tool call.\n",
        "\n",
        "print(\"Number of tool calls: \",len(response.output))\n",
        "# rich.print(response)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 389
        },
        "id": "gUjC_PQCcETm",
        "outputId": "53300e21-108d-4f02-d8f9-7d7dda5a6236"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Status =  completed\n",
            "\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m[\u001b[0m\n",
              "    \u001b[1;35mParsedResponseFunctionToolCall\u001b[0m\u001b[1m(\u001b[0m\n",
              "        \u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"latitude\":52.52,\"longitude\":13.405\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m,\n",
              "        \u001b[33mcall_id\u001b[0m=\u001b[32m'call_SpYMdNt34SA54MaRSk7mcwlT'\u001b[0m,\n",
              "        \u001b[33mname\u001b[0m=\u001b[32m'GetWeather'\u001b[0m,\n",
              "        \u001b[33mtype\u001b[0m=\u001b[32m'function_call'\u001b[0m,\n",
              "        \u001b[33mid\u001b[0m=\u001b[32m'fc_67e2eda6f49081928d5110677d234efd04e239c703fbd525'\u001b[0m,\n",
              "        \u001b[33mstatus\u001b[0m=\u001b[32m'completed'\u001b[0m,\n",
              "        \u001b[33mparsed_arguments\u001b[0m=\u001b[1;35mGetWeather\u001b[0m\u001b[1m(\u001b[0m\u001b[33mlatitude\u001b[0m=\u001b[1;36m52\u001b[0m\u001b[1;36m.52\u001b[0m, \u001b[33mlongitude\u001b[0m=\u001b[1;36m13\u001b[0m\u001b[1;36m.405\u001b[0m\u001b[1m)\u001b[0m\n",
              "    \u001b[1m)\u001b[0m,\n",
              "    \u001b[1;35mParsedResponseFunctionToolCall\u001b[0m\u001b[1m(\u001b[0m\n",
              "        \u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"latitude\":48.8566,\"longitude\":2.3522\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m,\n",
              "        \u001b[33mcall_id\u001b[0m=\u001b[32m'call_vDVZ82Eb6jz7Q5883QN99oHT'\u001b[0m,\n",
              "        \u001b[33mname\u001b[0m=\u001b[32m'GetWeather'\u001b[0m,\n",
              "        \u001b[33mtype\u001b[0m=\u001b[32m'function_call'\u001b[0m,\n",
              "        \u001b[33mid\u001b[0m=\u001b[32m'fc_67e2eda76fe08192a4111de8b190a0e704e239c703fbd525'\u001b[0m,\n",
              "        \u001b[33mstatus\u001b[0m=\u001b[32m'completed'\u001b[0m,\n",
              "        \u001b[33mparsed_arguments\u001b[0m=\u001b[1;35mGetWeather\u001b[0m\u001b[1m(\u001b[0m\u001b[33mlatitude\u001b[0m=\u001b[1;36m48\u001b[0m\u001b[1;36m.8566\u001b[0m, \u001b[33mlongitude\u001b[0m=\u001b[1;36m2\u001b[0m\u001b[1;36m.3522\u001b[0m\u001b[1m)\u001b[0m\n",
              "    \u001b[1m)\u001b[0m\n",
              "\u001b[1m]\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">[</span>\n",
              "    <span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ParsedResponseFunctionToolCall</span><span style=\"font-weight: bold\">(</span>\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">arguments</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'{\"latitude\":52.52,\"longitude\":13.405}'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">call_id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'call_SpYMdNt34SA54MaRSk7mcwlT'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'GetWeather'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'function_call'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'fc_67e2eda6f49081928d5110677d234efd04e239c703fbd525'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">status</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'completed'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">parsed_arguments</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">GetWeather</span><span style=\"font-weight: bold\">(</span><span style=\"color: #808000; text-decoration-color: #808000\">latitude</span>=<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">52.52</span>, <span style=\"color: #808000; text-decoration-color: #808000\">longitude</span>=<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">13.405</span><span style=\"font-weight: bold\">)</span>\n",
              "    <span style=\"font-weight: bold\">)</span>,\n",
              "    <span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ParsedResponseFunctionToolCall</span><span style=\"font-weight: bold\">(</span>\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">arguments</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'{\"latitude\":48.8566,\"longitude\":2.3522}'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">call_id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'call_vDVZ82Eb6jz7Q5883QN99oHT'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'GetWeather'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'function_call'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'fc_67e2eda76fe08192a4111de8b190a0e704e239c703fbd525'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">status</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'completed'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">parsed_arguments</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">GetWeather</span><span style=\"font-weight: bold\">(</span><span style=\"color: #808000; text-decoration-color: #808000\">latitude</span>=<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">48.8566</span>, <span style=\"color: #808000; text-decoration-color: #808000\">longitude</span>=<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2.3522</span><span style=\"font-weight: bold\">)</span>\n",
              "    <span style=\"font-weight: bold\">)</span>\n",
              "<span style=\"font-weight: bold\">]</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Number of tool calls:  2\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "In case of weather function it was random for me so we are sing example of different function to test multiple calls of same function in single response"
      ],
      "metadata": {
        "id": "V7TeuUMvcJCY"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "class SendEmail(BaseModel):\n",
        "    to: str = Field(..., description=\"Email address of the recipient\")\n",
        "    subject: str = Field(..., description=\"Subject of the email\")\n",
        "    body: str = Field(..., description=\"Body of the email\")\n",
        "\n",
        "\n",
        "def send_email(to, subject, body):\n",
        "    print(f\"Tool send_email Sending email to {to} with subject {subject}\")\n",
        "    print(f\"Body: {body}\")\n",
        "    print(f\"Email Tool call completed\")\n",
        "    return \"Email Sent\""
      ],
      "metadata": {
        "id": "ds6RgacxcL8a"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Using old way of sending history messages in every call"
      ],
      "metadata": {
        "id": "j6VEHNoPaSI1"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "First Step where model will responed with tool call request"
      ],
      "metadata": {
        "id": "Q4E9IoxrTzFV"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "messages=[\n",
        "    {\"role\": \"developer\", \"content\": \"You are a helpful assistant, you can send email about weather in a city. Email should be courteous and professional.\"},\n",
        "    {\"role\": \"user\", \"content\": \"send an email to first@gmail.com and second@gmail.com saying Hello\"}\n",
        "]\n",
        "tools = [pydantic_function_tool(SendEmail)]\n",
        "\n",
        "response = openai.responses.parse(\n",
        "    model=MODEL,\n",
        "    input=messages,\n",
        "    tools = tools\n",
        ")\n",
        "\n",
        "print(\"Status = \",response.status) # Status will not indicate the tool call\n",
        "print(response.output_text) # Empty\n",
        "rich.print(response.output)\n",
        "\n",
        "print(\"Number of tool calls: \",len(response.output))\n",
        "# rich.print(response)"
      ],
      "metadata": {
        "id": "2IPLSF30K--S",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 389
        },
        "outputId": "056b5eb8-80f1-4485-a6c8-d730050db980"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Status =  completed\n",
            "\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m[\u001b[0m\n",
              "    \u001b[1;35mParsedResponseFunctionToolCall\u001b[0m\u001b[1m(\u001b[0m\n",
              "        \u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"to\":\"first@gmail.com\",\"subject\":\"Hello\",\"body\":\"Hello\"\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m,\n",
              "        \u001b[33mcall_id\u001b[0m=\u001b[32m'call_86ZoIPJcqk5pEJ0sHJwk31wZ'\u001b[0m,\n",
              "        \u001b[33mname\u001b[0m=\u001b[32m'SendEmail'\u001b[0m,\n",
              "        \u001b[33mtype\u001b[0m=\u001b[32m'function_call'\u001b[0m,\n",
              "        \u001b[33mid\u001b[0m=\u001b[32m'fc_67e2edd21cf4819289f270631f84be2b079aae0081256c0a'\u001b[0m,\n",
              "        \u001b[33mstatus\u001b[0m=\u001b[32m'completed'\u001b[0m,\n",
              "        \u001b[33mparsed_arguments\u001b[0m=\u001b[1;35mSendEmail\u001b[0m\u001b[1m(\u001b[0m\u001b[33mto\u001b[0m=\u001b[32m'first@gmail.com'\u001b[0m, \u001b[33msubject\u001b[0m=\u001b[32m'Hello'\u001b[0m, \u001b[33mbody\u001b[0m=\u001b[32m'Hello'\u001b[0m\u001b[1m)\u001b[0m\n",
              "    \u001b[1m)\u001b[0m,\n",
              "    \u001b[1;35mParsedResponseFunctionToolCall\u001b[0m\u001b[1m(\u001b[0m\n",
              "        \u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"to\":\"second@gmail.com\",\"subject\":\"Hello\",\"body\":\"Hello\"\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m,\n",
              "        \u001b[33mcall_id\u001b[0m=\u001b[32m'call_ER1bZVvIHJ4KUie1Oc9k6jWR'\u001b[0m,\n",
              "        \u001b[33mname\u001b[0m=\u001b[32m'SendEmail'\u001b[0m,\n",
              "        \u001b[33mtype\u001b[0m=\u001b[32m'function_call'\u001b[0m,\n",
              "        \u001b[33mid\u001b[0m=\u001b[32m'fc_67e2edd272048192aa7ce16b317c9b42079aae0081256c0a'\u001b[0m,\n",
              "        \u001b[33mstatus\u001b[0m=\u001b[32m'completed'\u001b[0m,\n",
              "        \u001b[33mparsed_arguments\u001b[0m=\u001b[1;35mSendEmail\u001b[0m\u001b[1m(\u001b[0m\u001b[33mto\u001b[0m=\u001b[32m'second@gmail.com'\u001b[0m, \u001b[33msubject\u001b[0m=\u001b[32m'Hello'\u001b[0m, \u001b[33mbody\u001b[0m=\u001b[32m'Hello'\u001b[0m\u001b[1m)\u001b[0m\n",
              "    \u001b[1m)\u001b[0m\n",
              "\u001b[1m]\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">[</span>\n",
              "    <span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ParsedResponseFunctionToolCall</span><span style=\"font-weight: bold\">(</span>\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">arguments</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'{\"to\":\"first@gmail.com\",\"subject\":\"Hello\",\"body\":\"Hello\"}'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">call_id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'call_86ZoIPJcqk5pEJ0sHJwk31wZ'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'SendEmail'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'function_call'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'fc_67e2edd21cf4819289f270631f84be2b079aae0081256c0a'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">status</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'completed'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">parsed_arguments</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">SendEmail</span><span style=\"font-weight: bold\">(</span><span style=\"color: #808000; text-decoration-color: #808000\">to</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'first@gmail.com'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">subject</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'Hello'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">body</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'Hello'</span><span style=\"font-weight: bold\">)</span>\n",
              "    <span style=\"font-weight: bold\">)</span>,\n",
              "    <span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ParsedResponseFunctionToolCall</span><span style=\"font-weight: bold\">(</span>\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">arguments</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'{\"to\":\"second@gmail.com\",\"subject\":\"Hello\",\"body\":\"Hello\"}'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">call_id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'call_ER1bZVvIHJ4KUie1Oc9k6jWR'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'SendEmail'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'function_call'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'fc_67e2edd272048192aa7ce16b317c9b42079aae0081256c0a'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">status</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'completed'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">parsed_arguments</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">SendEmail</span><span style=\"font-weight: bold\">(</span><span style=\"color: #808000; text-decoration-color: #808000\">to</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'second@gmail.com'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">subject</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'Hello'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">body</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'Hello'</span><span style=\"font-weight: bold\">)</span>\n",
              "    <span style=\"font-weight: bold\">)</span>\n",
              "<span style=\"font-weight: bold\">]</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Number of tool calls:  2\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "Second Step where we are calling the `send_email` function and sending the response back to Responses API.\n",
        "\n",
        "But this time we are running a loop on `response.output` to call all the functions"
      ],
      "metadata": {
        "id": "-EJUa5FWafKE"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Defining a function in which We will call the relevant function\n",
        "# and return the new message object\n",
        "def handle_tool_call_responses(tool_call):\n",
        "    result = send_email(tool_call.parsed_arguments.to, tool_call.parsed_arguments.subject,tool_call.parsed_arguments.body)\n",
        "\n",
        "    new_message = {\n",
        "        \"type\": \"function_call_output\",\n",
        "        \"call_id\": tool_call.call_id,\n",
        "        \"output\": str(result)\n",
        "    }\n",
        "    return new_message"
      ],
      "metadata": {
        "id": "fP7XJLvCayCL"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Logic here is bit different then what we have done in Chat API\n",
        "tool_call_results = []\n",
        "for tool_call in response.output:\n",
        "    if tool_call.type == \"function_call\": # check if the output's type is function_call\n",
        "        # Adding the result of tool calls individually\n",
        "        tool_call_results.append(handle_tool_call_responses(tool_call))\n",
        "\n",
        "# deleting the parsed_arguments from the response.output because to\n",
        "# sending messages as history to the API, we need to remove the parsed_arguments\n",
        "for item in response.output:\n",
        "    del item.parsed_arguments\n",
        "\n",
        "# For multiple tool calls, we need to append the output of each tool call individually.\n",
        "# This is different from Chat API in which we can just send message object which have all the tool calls\n",
        "# extend function it adds each item from the iterable one by one.\n",
        "messages.extend(response.output)\n",
        "messages.extend(tool_call_results) # Adding the result of tool calls individually\n",
        "# rich.print(messages)\n",
        "response2 = openai.responses.parse(model=MODEL, input=messages,tools = tools)\n",
        "print(\"Model Response2 output_text = \",response2.output_text)\n",
        "# rich.print(\"Model Response2 = \",response2)\n",
        "print(\"Status = \",response2.status)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "s3hIndi_cdG7",
        "outputId": "e23609ff-8c51-483a-890c-646c38792e97"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Tool send_email Sending email to first@gmail.com with subject Hello\n",
            "Body: Hello\n",
            "Email Tool call completed\n",
            "Tool send_email Sending email to second@gmail.com with subject Hello\n",
            "Body: Hello\n",
            "Email Tool call completed\n",
            "Model Response2 output_text =  The emails saying \"Hello\" have been successfully sent to both first@gmail.com and second@gmail.com. If you need anything else, feel free to ask!\n",
            "Status =  completed\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Using new way of conversation state by sending perivous reponse id"
      ],
      "metadata": {
        "id": "1kt-4nnsa089"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "First Step where model will responed with tool call request"
      ],
      "metadata": {
        "id": "wWo6BoJfa3hZ"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# This section is same as above\n",
        "messages=[\n",
        "    {\"role\": \"developer\", \"content\": \"You are a helpful assistant, you can send email about weather in a city. Email should be courteous and professional.\"},\n",
        "    {\"role\": \"user\", \"content\": \"send an email to first@gmail.com and second@gmail.com saying Hello\"}\n",
        "]\n",
        "tools = [pydantic_function_tool(SendEmail)]\n",
        "\n",
        "response = openai.responses.parse(\n",
        "    model=MODEL,\n",
        "    input=messages,\n",
        "    tools = tools\n",
        ")\n",
        "\n",
        "print(\"Status = \",response.status) # Status will not indicate the tool call\n",
        "print(response.output_text) # Empty\n",
        "rich.print(response.output)\n",
        "\n",
        "print(\"Number of tool calls: \",len(response.output))\n",
        "# rich.print(response)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 389
        },
        "id": "ePKGsA50a1Qx",
        "outputId": "7b4567d5-325c-4407-92d5-9cc3295642cd"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Status =  completed\n",
            "\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m[\u001b[0m\n",
              "    \u001b[1;35mParsedResponseFunctionToolCall\u001b[0m\u001b[1m(\u001b[0m\n",
              "        \u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"to\":\"first@gmail.com\",\"subject\":\"Hello\",\"body\":\"Hello!\"\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m,\n",
              "        \u001b[33mcall_id\u001b[0m=\u001b[32m'call_jgGqQFnEgg5A0oLCQoUZTHtM'\u001b[0m,\n",
              "        \u001b[33mname\u001b[0m=\u001b[32m'SendEmail'\u001b[0m,\n",
              "        \u001b[33mtype\u001b[0m=\u001b[32m'function_call'\u001b[0m,\n",
              "        \u001b[33mid\u001b[0m=\u001b[32m'fc_67e2ee2c2f948192bcc1033c65ce3d6e07a988a7a0586cab'\u001b[0m,\n",
              "        \u001b[33mstatus\u001b[0m=\u001b[32m'completed'\u001b[0m,\n",
              "        \u001b[33mparsed_arguments\u001b[0m=\u001b[1;35mSendEmail\u001b[0m\u001b[1m(\u001b[0m\u001b[33mto\u001b[0m=\u001b[32m'first@gmail.com'\u001b[0m, \u001b[33msubject\u001b[0m=\u001b[32m'Hello'\u001b[0m, \u001b[33mbody\u001b[0m=\u001b[32m'Hello!'\u001b[0m\u001b[1m)\u001b[0m\n",
              "    \u001b[1m)\u001b[0m,\n",
              "    \u001b[1;35mParsedResponseFunctionToolCall\u001b[0m\u001b[1m(\u001b[0m\n",
              "        \u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"to\":\"second@gmail.com\",\"subject\":\"Hello\",\"body\":\"Hello!\"\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m,\n",
              "        \u001b[33mcall_id\u001b[0m=\u001b[32m'call_bctngnqF2NSWIIZNA8uz9E76'\u001b[0m,\n",
              "        \u001b[33mname\u001b[0m=\u001b[32m'SendEmail'\u001b[0m,\n",
              "        \u001b[33mtype\u001b[0m=\u001b[32m'function_call'\u001b[0m,\n",
              "        \u001b[33mid\u001b[0m=\u001b[32m'fc_67e2ee2c73c08192b4d147c17f9946df07a988a7a0586cab'\u001b[0m,\n",
              "        \u001b[33mstatus\u001b[0m=\u001b[32m'completed'\u001b[0m,\n",
              "        \u001b[33mparsed_arguments\u001b[0m=\u001b[1;35mSendEmail\u001b[0m\u001b[1m(\u001b[0m\u001b[33mto\u001b[0m=\u001b[32m'second@gmail.com'\u001b[0m, \u001b[33msubject\u001b[0m=\u001b[32m'Hello'\u001b[0m, \u001b[33mbody\u001b[0m=\u001b[32m'Hello!'\u001b[0m\u001b[1m)\u001b[0m\n",
              "    \u001b[1m)\u001b[0m\n",
              "\u001b[1m]\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">[</span>\n",
              "    <span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ParsedResponseFunctionToolCall</span><span style=\"font-weight: bold\">(</span>\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">arguments</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'{\"to\":\"first@gmail.com\",\"subject\":\"Hello\",\"body\":\"Hello!\"}'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">call_id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'call_jgGqQFnEgg5A0oLCQoUZTHtM'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'SendEmail'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'function_call'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'fc_67e2ee2c2f948192bcc1033c65ce3d6e07a988a7a0586cab'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">status</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'completed'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">parsed_arguments</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">SendEmail</span><span style=\"font-weight: bold\">(</span><span style=\"color: #808000; text-decoration-color: #808000\">to</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'first@gmail.com'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">subject</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'Hello'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">body</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'Hello!'</span><span style=\"font-weight: bold\">)</span>\n",
              "    <span style=\"font-weight: bold\">)</span>,\n",
              "    <span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ParsedResponseFunctionToolCall</span><span style=\"font-weight: bold\">(</span>\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">arguments</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'{\"to\":\"second@gmail.com\",\"subject\":\"Hello\",\"body\":\"Hello!\"}'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">call_id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'call_bctngnqF2NSWIIZNA8uz9E76'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'SendEmail'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'function_call'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'fc_67e2ee2c73c08192b4d147c17f9946df07a988a7a0586cab'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">status</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'completed'</span>,\n",
              "        <span style=\"color: #808000; text-decoration-color: #808000\">parsed_arguments</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">SendEmail</span><span style=\"font-weight: bold\">(</span><span style=\"color: #808000; text-decoration-color: #808000\">to</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'second@gmail.com'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">subject</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'Hello'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">body</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'Hello!'</span><span style=\"font-weight: bold\">)</span>\n",
              "    <span style=\"font-weight: bold\">)</span>\n",
              "<span style=\"font-weight: bold\">]</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Number of tool calls:  2\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "Second Step where we are calling the `send_email` function and sending the response back to Responses API.\n",
        "\n",
        "But this time we are running a loop on `response.output` to call all the functions"
      ],
      "metadata": {
        "id": "6uIbmV86a8Wa"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# This section is same as above\n",
        "\n",
        "# Call the relevant function and return the output\n",
        "def handle_tool_call_responses(tool_call):\n",
        "    result = send_email(tool_call.parsed_arguments.to, tool_call.parsed_arguments.subject,tool_call.parsed_arguments.body)\n",
        "\n",
        "    new_message = {\n",
        "        \"type\": \"function_call_output\",\n",
        "        \"call_id\": tool_call.call_id,\n",
        "        \"output\": str(result)\n",
        "    }\n",
        "    return new_message"
      ],
      "metadata": {
        "id": "nAif9Tq6a8_B"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "The only difference in below section is how messages are sent."
      ],
      "metadata": {
        "id": "iWK90k29cvYk"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# The only difference in this section is how messages are sent.\n",
        "\n",
        "# Logic here is bit different then what we have done in Chat API\n",
        "tool_call_results = []\n",
        "for tool_call in response.output:\n",
        "    if tool_call.type == \"function_call\": # check if the output's type is function_call\n",
        "        tool_call_results.append(handle_tool_call_responses(tool_call))\n",
        "\n",
        "# Not needed now because we are using response.id\n",
        "# for item in response.output:\n",
        "#     del item.parsed_arguments\n",
        "\n",
        "# Not needed now because we are using response.id\n",
        "# messages.extend(response.output)\n",
        "\n",
        "# Emptying the messages array because we are sending the previous response id,\n",
        "# therefore we don't need to send the previous message\n",
        "messages = []\n",
        "# Adding the result of tool calls individually\n",
        "messages.extend(tool_call_results)\n",
        "# rich.print(messages)\n",
        "response2 = openai.responses.parse(model=MODEL, input=messages,tools = tools, previous_response_id=response.id)\n",
        "print(\"Model Response2 output_text = \",response2.output_text)\n",
        "# rich.print(\"Model Response2 = \",response2)\n",
        "print(\"Status = \",response2.status)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "JzZb8aRYcvvT",
        "outputId": "f607c1e5-e4ab-43bb-acdb-873ac5034438"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Tool send_email Sending email to first@gmail.com with subject Hello\n",
            "Body: Hello!\n",
            "Email Tool call completed\n",
            "Tool send_email Sending email to second@gmail.com with subject Hello\n",
            "Body: Hello!\n",
            "Email Tool call completed\n",
            "Model Response2 output_text =  I have sent an email saying \"Hello!\" to both first@gmail.com and second@gmail.com. If you need further assistance, feel free to ask!\n",
            "Status =  completed\n"
          ]
        }
      ]
    }
  ]
}